//////////////////////////////////////////////////////////////////////////

#ifndef _CONNECTION_H_
#define _CONNECTION_H_

//////////////////////////////////////////////////////////////////////////

#ifndef _OBSERVABLE_H_
#include "observable.h"
#endif

#ifndef _NETWORKPACKET_H_
#include "networkpacket.h"
#endif

#ifndef _MUTEX_H_
#include "mutex.h"
#endif

#include <queue>
#include <boost/shared_ptr.hpp>

//////////////////////////////////////////////////////////////////////////

class ConnectionImpl;

//////////////////////////////////////////////////////////////////////////


/** Network connection
*
*  @author   Pasechnik Roman
*  @since    Jun 29th, 2009
*  @updated  Nov 11th, 2009
*/
class Connection : public Observable,
                   public Observer
{
//////////////////////////////////////////////////////////////////////////

public:

//////////////////////////////////////////////////////////////////////////


    /** Working mode */
    enum Mode
    {
        CLIENT,
        SERVER
    };


    /** Constructor */
    Connection( Mode _workingMode );


    /** Destructor */
    virtual ~Connection();


//////////////////////////////////////////////////////////////////////////


    /** Send TCP */
    void SendTCP( const NetworkPacket& _data );


    /** Send UDP */
    void SendUDP( const NetworkPacket& _data );


//////////////////////////////////////////////////////////////////////////


    /** Recv TCP */
    const NetworkPacket& GetRecvDataTCP() const;


    /** Recv UDP */
    const NetworkPacket& GetRecvDataUDP() const;


//////////////////////////////////////////////////////////////////////////


    /** Connect to server (client only) */
    void Connect( const char* _address );


    /** Accept new connection (server only) */
    void Accept();


    /** Close connection */
    void Close();


////////////////////////////////////////////////////////////////////////////////


    /** Is client connected to server */
    bool IsConnected() const;


////////////////////////////////////////////////////////////////////////////////


    /** Get connection ID */
    size_t GetID() const;


//////////////////////////////////////////////////////////////////////////

private:

////////////////////////////////////////////////////////////////////////////////
//// Observer interface implementation
////////////////////////////////////////////////////////////////////////////////


    /** Notify observer about event */
    virtual void OnEvent( Event _event, Observable* _observable );


////////////////////////////////////////////////////////////////////////////////


    /** Send a packet from TCP queue */
    void StartSendTCP();


    /** Send a packet from UDP queue */
    void StartSendUDP();


    /** SendTCP handler */
    void HandleSendTCP();


    /** SendUDP handler */
    void HandleSendUDP();


//////////////////////////////////////////////////////////////////////////


    /** Connection impl */
    ConnectionImpl* m_Impl;


    /** Connection ID */
    size_t m_ID;


    /** [Utility type]: A queue of network packets */
    typedef std::queue<NetworkPacket> PacketQueue;


    /** TCP packet queue */
    PacketQueue m_TCPQueue;


    /** UDP packet queue */
    PacketQueue m_UDPQueue;


    /** TCP packet queue mutex */
    Mutex m_TCPQueueMutex;


    /** UDP packet queue mutex */
    Mutex m_UDPQueueMutex;


//////////////////////////////////////////////////////////////////////////
};


/** [Utility type]: a pointer to connection */
typedef boost::shared_ptr<Connection> ConnectionPtr;


//////////////////////////////////////////////////////////////////////////

#endif

//////////////////////////////////////////////////////////////////////////
